package com.falm.picturebackend.util;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;

import com.falm.picturebackend.entity.VO.UserVO;

import cn.hutool.json.JSONObject;
import cn.hutool.jwt.JWTPayload;
import cn.hutool.jwt.signers.JWTSigner;
import cn.hutool.jwt.signers.JWTSignerUtil;

/**
 * @author Administrator
 */
public class JWTUtil {

    /**
     * 密钥
     */
    @Value("${jwt.secret}")
    private static final String SECRET = "falm";

    /**
     * 过期时间，默认值7天
     */
    @Value("${jwt.exp}")
    private static final Integer EXP = 1000 * 60 * 60 * 24 * 7;

    /**
     * 创建JWT
     * 
     * @param userVO 返回前端应用信息
     * @return JWT
     */
    public static String createJwt(UserVO userVO) {

        Map<String, Object> headerMap = new HashMap<>();
        headerMap.put("alg", "HS256");
        headerMap.put("typ", "JWT");

        Map<String, Object> payloadMap = new HashMap<>();
        // 负载用户信息
        payloadMap.put("user", userVO);
        // 签发时间
        payloadMap.put("iat", System.currentTimeMillis());
        // 过期时间
        payloadMap.put("exp", System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 7);
        // 生效时间
        payloadMap.put("nbf", System.currentTimeMillis());
        // 唯一标识
        payloadMap.put("jti", StringUtils.join("JWT_", userVO.getUserAccount(), "_", System.currentTimeMillis()));

        // 签名
        JWTSigner signer = JWTSignerUtil.hs256(SECRET.getBytes(StandardCharsets.UTF_8));

        // 生产JWT
        return cn.hutool.jwt.JWTUtil.createToken(headerMap, payloadMap, signer);
    }

    private static JWTPayload parseJwtGetPayload(String jwt) {
        return cn.hutool.jwt.JWTUtil.parseToken(jwt).getPayload();
    }

    /**
     * 获取用户信息
     * 
     * @param jwt JWT
     * @return 解析结果
     */
    public static UserVO parseJwtGetUserInfo(String jwt) {
        JSONObject userJsonObject = (JSONObject)parseJwtGetPayload(jwt).getClaim("user");
        return userJsonObject.toBean(UserVO.class);
    }

    /**
     * 验证JWT
     * 
     * @param jwt JWT
     * @return 是否正确
     */
    public static boolean verifyJwt(String jwt) {
        if (StringUtils.isBlank(jwt)) {
            return false;
        }
        // 检查Token是否在黑名单中
        if (TokenBlackListUtil.isInBlackList(jwt)) {
            return false;
        }

        boolean verify = cn.hutool.jwt.JWTUtil.verify(jwt, SECRET.getBytes(StandardCharsets.UTF_8));
        JWTPayload jwtPayload = parseJwtGetPayload(jwt);
        // 签发时间
        Long iat = (Long)jwtPayload.getClaim("iat");
        // 过期时间
        Long exp = (Long)jwtPayload.getClaim("exp");
        // 生效时间
        Long nbf = (Long)jwtPayload.getClaim("nbf");
        // 需要验证通过，且时间有效返回true

        return verify && System.currentTimeMillis() >= iat && System.currentTimeMillis() <= exp
            && System.currentTimeMillis() >= nbf;
    }

    /**
     * 延长JWT有效时间
     * 
     * @param jwt JWT
     * @return 新的JWT
     */
    public static String delayTime(String jwt) {
        // 获取负载
        JWTPayload jwtPayload = parseJwtGetPayload(jwt);
        jwtPayload.setPayload("exp", System.currentTimeMillis() + EXP);
        return cn.hutool.jwt.JWTUtil.createToken(jwtPayload.getClaimsJson(), SECRET.getBytes(StandardCharsets.UTF_8));
    }

}